Golang 读取配置文件之 viper 包
作者spf13有两个明星项目—cobra & viper (眼睛蛇与蝮蛇)
Cobra 已经学习了,这里主要介绍下 viper 咋用
viper 用来读取初始的配置文件
设置默认值
一个好的项目需要在引入配置文件之前使用一些默认值,可以通过以下方式构建
viper.SetDefault("ContentDir", "content")
viper.SetDefault("LayoutDir", "layouts")
viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})
读取配置文件
支持的配置文件格式:JSON, TOML, YAML, HCL, envfile and Java properties config files Viper 可以搜索多个路径,但单个 Viper 实例只支持单个配置文件。
具体的使用规则如下:
// 加载配置文件之前,设置一些配置
viper.SetConfigName("config") // 配置文件名称
viper.SetConfigType("yaml") // 配置文件的拓展名
viper.AddConfigPath("/etc/appname/") // 配置文件的路径
viper.AddConfigPath("$HOME/.appname") // 可设置多个搜索路径
viper.AddConfigPath(".") // 可选在当前工作空间中查找
err := viper.ReadInConfig() // 找到并加载配置文件
if err != nil { // 处理错误
panic(fmt.Errorf("Fatal error config file: %w \n", err))
}
运行时读取配置文件
确保在调用 WatchConfig()
之前添加了所有的 configPaths
viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Config file changed:", e.Name)
})
viper.WatchConfig()
从IO流中读取配置文件
viper.SetConfigType("yaml") // or viper.SetConfigType("YAML")
// any approach to require this configuration into your program.
var yamlExample = []byte(`
Hacker: true
name: steve
hobbies:
- skateboarding
- snowboarding
- go
clothing:
jacket: leather
trousers: denim
age: 35
eyes : brown
beard: true
`)
viper.ReadConfig(bytes.NewBuffer(yamlExample))
viper.Get("name") // this would be "steve"
Get 值
Get(key string) : interface{}
GetBool(key string) : bool
GetFloat64(key string) : float64
GetInt(key string) : int
GetIntSlice(key string) : []int
GetString(key string) : string
GetStringMap(key string) : map[string]interface{}
GetStringMapString(key string) : map[string]string
GetStringSlice(key string) : []string
GetTime(key string) : time.Time
GetDuration(key string) : time.Duration
IsSet(key string) : bool
AllSettings() : map[string]interface{}
如果没有找到,每个Get函数将返回一个零值。为了检查给定的键是否存在,提供了 IsSet()
方法。
获取多重嵌套的Key、数组:
// {
// "host": {
// "address": "localhost",
// "ports": [
// 5799,
// 6029
// ]
// },
// "datastore": {
// "metric": {
// "host": "127.0.0.1",
// "port": 3099
// },
// "warehouse": {
// "host": "198.0.0.1",
// "port": 2112
// }
// }
// }
GetInt("host.ports.1") // returns 6029
注意: 如果有与上述方法中 .
取健相同,那么就使用该健(下面第一行)
// {
// "datastore.metric.host": "0.0.0.0",
// "host": {
// "address": "localhost",
// "port": 5799
// },
// "datastore": {
// "metric": {
// "host": "127.0.0.1",
// "port": 3099
// },
// "warehouse": {
// "host": "198.0.0.1",
// "port": 2112
// }
// }
// }
GetString("datastore.metric.host") // returns "0.0.0.0"
重设值与覆盖、键使用别名
viper.Set("Verbose", true)
viper.Set("LogFile", LogFile)
// 注册
viper.RegisterAlias("loud", "Verbose")
viper.Set("verbose", true) // same result as next line
viper.Set("loud", true) // same result as prior line
viper.GetBool("loud") // true
viper.GetBool("verbose") // true
覆写配置文件
// 如果存在,则将当前 viper 配置写入预定义路径。如果没有预定义的路径,则返回错误。将覆盖当前配置文件,如果它存在。
viper.WriteConfig() // 将viper中的配置保存到'viper.AddConfigPath()' and 'viper.SetConfigName'预定义的配置文件中
// 将当前的 viper 配置写入预定义的路径。如果没有预定义的路径,则返回错误。将不会覆盖当前配置文件,如果它存在。
viper.SafeWriteConfig()
// 将当前 viper 配置写入给定的文件路径。将覆盖给定的文件,如果它存在。
viper.WriteConfigAs("/path/to/my/.config")
viper.SafeWriteConfigAs("/path/to/my/.config") // will error since it has already been written
// 将当前的 viper 配置写入给定的文件路径。如果给定的文件存在,则不会覆盖该文件。
viper.SafeWriteConfigAs("/path/to/my/.other_config")
读取配置文件示例
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var (
// Used for flags.
cfgFile string
userLicense string
rootCmd = &cobra.Command{
Use: "cobra",
Short: "A generator for Cobra based Applications",
Long: `Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
}
)
// Execute executes the root command.
func Execute() error {
return rootCmd.Execute()
}
func init() {
// 初始化操作
cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution")
rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project")
rootCmd.PersistentFlags().Bool("viper", true, "use Viper for configuration")
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
viper.SetDefault("license", "apache")
rootCmd.AddCommand(addCmd)
rootCmd.AddCommand(initCmd)
}
// 一般在这里读取配置文件或者环境变量
func initConfig() {
if cfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
} else {
// Find home directory.
home, err := os.UserHomeDir()
cobra.CheckErr(err)
// 搜索在 home 目录下后缀名为 .cobra 的配置文件(可以自定义)
viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".cobra")
}
// read in environment variables that match
viper.AutomaticEnv()
if err := viper.ReadInConfig(); err == nil {
fmt.Println("Using config file:", viper.ConfigFileUsed())
}
}